package com.gulimall.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gulimall.common.utils.PageUtils;
import com.gulimall.common.utils.Query;
import com.gulimall.product.dao.CategoryDao;
import com.gulimall.product.entity.CategoryEntity;
import com.gulimall.product.service.CategoryService;
import com.gulimall.product.vo.Category2vo;
import com.gulimall.product.vo.Category3vo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service("categoryService")
@Slf4j
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    private CategoryDao categoryDao;


    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redisson;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }


    public  List<CategoryEntity> getCatelogListByPid(List<CategoryEntity> all ,long pid){

        return  all.stream().filter((category)-> category.getParentCid()==pid).collect(Collectors.toList());


    }

    public HashMap<String, List<Category2vo>>  cateloglistjsonredis() {
        // 如何存  类型  key  value  规范:前缀，有效时间【业务】   同步：实时 canel  redisTemplate.set("categorylistjsonredis","")    很容易冲突  product:category:categorylistcache

        RLock rlock = redisson.getReadWriteLock("categorylistcachelock").writeLock();


        rlock.lock(); //默认30s

        try{
            String cache = redisTemplate.opsForValue().get("product:category:categorylistcache");

            if(!StringUtils.isEmpty(cache)){
                log.info("缓存命中");
                return JSON.parseObject(cache,new TypeReference<HashMap<String, List<Category2vo>>>(){});
            }else{
                log.info("命中数据库");
                HashMap<String, List<Category2vo>> cateloglistjsondb = cateloglistjsondb();//耗时操作
                redisTemplate.opsForValue().set("product:category:categorylistcache",JSON.toJSONString(cateloglistjsondb),1l, TimeUnit.HOURS);
                return cateloglistjsondb;

            }
        }finally {
            rlock.unlock();
        }






    }


//    public HashMap<String, List<Category2vo>>  cateloglistjsonredis() {
//        // 如何存  类型  key  value  规范:前缀，有效时间【业务】   同步：实时 canel  redisTemplate.set("categorylistjsonredis","")    很容易冲突  product:category:categorylistcache
//
//        String cache = redisTemplate.opsForValue().get("product:category:categorylistcache");
//
//
//
//
//        if(!StringUtils.isEmpty(cache)){
//            log.info("缓存命中");
//
//
//            return JSON.parseObject(cache,new TypeReference<HashMap<String, List<Category2vo>>>(){});
//
//        }else{
//
//
//            String uuid = UUID.randomUUID().toString();
//
//            Boolean isLocked = redisTemplate.opsForValue().setIfAbsent("categorylistcachelock", uuid, 10l, TimeUnit.SECONDS);
//
//            if(isLocked){//获取资源
//                try{
//                    log.info("命中数据库");
//
//                    HashMap<String, List<Category2vo>> cateloglistjsondb = cateloglistjsondb();//耗时操作
//                    redisTemplate.opsForValue().set("product:category:categorylistcache",JSON.toJSONString(cateloglistjsondb),1l, TimeUnit.HOURS);
//                    return cateloglistjsondb;
//                }finally{
////                        String categorylistcachelock = redisTemplate.opsForValue().get("categorylistcachelock");
////                        if(uuid.equals(categorylistcachelock)){   // lua脚本保证原子性
////
////                            //时间片到期了
////                            redisTemplate.delete("categorylistcachelock");
////                        }
//
//                    String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
//                    //删除锁   采用lua脚本保证原子性
//                    redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("categorylistcachelock"), uuid);
//                }
//
//
//            }else{//没有获取资源，该干什么？  自旋[一直在自旋]
//
//                try {
//                    Thread.sleep(3000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                return cateloglistjsonredis();
//
//            }
//
//
//
//        }
//
//
//
//
//    }

    private HashMap<String, List<Category2vo>> cateloglistjsondb() {

        HashMap<String, List<Category2vo>>  map = new HashMap();


        // 所有的分类
        List<CategoryEntity> all = categoryDao.selectList(null);


        //1. 解决一级分类
        List<CategoryEntity> category1Entities = getCatelogListByPid(all,0l);

        List<CategoryEntity> category2Entities = null;
        List<CategoryEntity> category3Entities = null;
        Category2vo category2vo = null;
        Category3vo category3vo = null;

        for (CategoryEntity category1Entity : category1Entities) {
            //2. 构造二级分类列表
            category2Entities = getCatelogListByPid(all,category1Entity.getCatId());

            List<Category2vo>  category2vos = new ArrayList();
            List<Category3vo>  category3vos =null;
            for (CategoryEntity category2Entity : category2Entities) {
                category2vo = new Category2vo();
                category2vo.setId(category2Entity.getCatId()+"");
                category2vo.setName(category2Entity.getName());
                category2vo.setCatalog1Id(category1Entity.getCatId().toString());


                //构建3级分类
                category3Entities = getCatelogListByPid(all,category2Entity.getCatId());

                category3vos = new ArrayList();
                for (CategoryEntity category3Entity : category3Entities) {



                    category3vo = new Category3vo();
                    category3vo.setId(category3Entity.getCatId().toString());
                    category3vo.setName(category3Entity.getName());
                    category3vo.setCatalog2Id(category2Entity.getCatId().toString());

                    category3vos.add(category3vo);

                }

                category2vo.setCatalog3List(category3vos);


                category2vos.add(category2vo);

                
            }



            map.put(category1Entity.getCatId().toString(),category2vos);
        }

        return map;
    }



}